package com.suyeer.basic.bean;

import com.alibaba.fastjson.annotation.JSONField;
import com.suyeer.basic.util.BasicUtil;
import com.suyeer.basic.util.JsonUtil;
import com.suyeer.basic.util.RSAUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Serializable;

import static com.suyeer.basic.util.ConstUtil.*;

/**
 * @author jun 2018/10/19
 */
public abstract class BaseHttpResContent<T> implements Serializable {
    private static final long serialVersionUID = -5764986016352461610L;
    protected transient Object userInfo;
    protected transient Object wxUserInfo;
    protected transient Boolean isLogin;
    protected transient Boolean isWxLogin;
    private Integer code;
    private String message;
    private T result;
    private transient String funcDes;
    private transient String userIp;
    private transient String reqURL;
    private transient String reqURI;
    private transient String reqQueryURL;
    private transient String reqQueryURI;
    private transient String reqQuery;
    private transient String reqMethod;
    private transient String reqParams;
    private transient String sessionId;
    private transient String userAgent;
    private transient String wxRedirect;
    private transient String referrer;
    private transient HttpSession httpSession;
    private transient HttpServletRequest request;
    private transient HttpServletResponse response;

    public BaseHttpResContent() {
    }

    public BaseHttpResContent(HttpServletRequest request, HttpServletResponse response) {
        init(request, response);
    }

    public void init(HttpServletRequest request, HttpServletResponse response) {
        this.code = 200;
        this.message = "";
        this.reqURI = "";
        this.reqURL = "";
        this.reqQueryURI = "";
        this.reqQueryURL = "";
        this.reqParams = "";
        this.userIp = "";
        this.isLogin = false;
        this.response = response;
        this.request = request;
        if (request != null) {
            this.reqQuery = StringUtils.isNotBlank(request.getQueryString()) ? "?" + request.getQueryString() : "";
            this.reqURI = request.getRequestURI();
            this.reqURL = request.getRequestURL().toString();
            this.reqQueryURI = this.reqURI + this.reqQuery;
            this.reqQueryURL = this.reqURL + this.reqQuery;
            this.reqParams = JsonUtil.toString(request.getParameterMap());
            this.reqMethod = request.getMethod();
            this.httpSession = request.getSession();
            this.userIp = BasicUtil.getUserIp(request);
            this.userAgent = request.getHeader(USER_AGENT);
            this.referrer = BasicUtil.getReferrer(request);
            if (this.httpSession != null) {
                this.sessionId = this.httpSession.getId();
                this.userInfo = this.httpSession.getAttribute(SESSION_CURRENT_LOGIN_USER_INFO);
                this.wxUserInfo = this.httpSession.getAttribute(SESSION_CURRENT_WX_LOGIN_USER_INFO);
            }
            this.isLogin = (this.userInfo != null);
            this.isWxLogin = (this.wxUserInfo != null);
        }
    }

    public void fillData(Integer code, String message, T result) {
        this.code = code;
        this.message = message;
        this.result = result;
    }

    public void setUserSession(Object userObj) {
        if (this.httpSession != null) {
            this.userInfo = userObj;
            this.httpSession.setAttribute(SESSION_CURRENT_LOGIN_USER_INFO, userObj);
        }
    }

    public void removeUserSession() {
        if (this.httpSession != null) {
            this.httpSession.removeAttribute(SESSION_CURRENT_LOGIN_USER_INFO);
        }
    }

    public void setWxUserSession(Object wxUserObj) {
        if (this.httpSession != null) {
            this.wxUserInfo = wxUserObj;
            this.httpSession.setAttribute(SESSION_CURRENT_WX_LOGIN_USER_INFO, wxUserObj);
        }
    }

    public void saveOriginalQueryURI() {
        if (this.httpSession != null) {
            this.httpSession.setAttribute(SESSION_CURRENT_WX_ORIGINAL_QUERY_URI_INFO, this.reqQueryURI);
        }
    }

    @JSONField(serialize = false)
    public String getOriginalQueryURI() {
        return (String) this.httpSession.getAttribute(SESSION_CURRENT_WX_ORIGINAL_QUERY_URI_INFO);
    }

    public void removeWxUserSession() {
        if (this.httpSession != null) {
            this.httpSession.removeAttribute(SESSION_CURRENT_WX_LOGIN_USER_INFO);
        }
    }

    public Integer getCode() {
        return this.code;
    }

    public String getMessage() {
        return this.message;
    }

    public T getResult() {
        return this.result;
    }

    public String getReqParams() {
        return this.reqParams;
    }

    public String getSessionId() {
        return this.sessionId;
    }

    public HttpSession getHttpSession() {
        return this.httpSession;
    }

    public String getUserIp() {
        return this.userIp;
    }

    public String getReqMethod() {
        return this.reqMethod;
    }

    public String getFuncDes() {
        if (StringUtils.isNotBlank(funcDes)) {
            return funcDes;
        }
        if (this.request != null) {
            return (String) this.request.getAttribute(KEY_FOR_FUNCTION_NAME);
        }
        return null;
    }

    public void setFuncDes(String funcDes) {
        this.funcDes = funcDes;
        if (this.request != null) {
            this.request.setAttribute(KEY_FOR_FUNCTION_NAME, funcDes);
        }
    }

    public String getReqURL() {
        return reqURL;
    }

    public String getReqURI() {
        return reqURI;
    }

    public String getReqQueryURL() {
        return reqQueryURL;
    }

    public String getReqQueryURI() {
        return reqQueryURI;
    }

    public String getReqQuery() {
        return reqQuery;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public String getReferrer() {
        return referrer;
    }

    public String getWxRedirect() {
        return wxRedirect;
    }

    public void setWxRedirect(String wxRedirect) {
        this.wxRedirect = wxRedirect;
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public void allowALLOrigin() {
        allowOrigin(ALLOW_ALL_ORIGIN);
    }

    public void allowOrigin(String allowOrigin) {
        if (this.response != null) {
            this.response.setHeader(ALLOW_ORIGIN, allowOrigin);
        }
    }

    /**
     * isPermission
     *
     * @return Boolean
     */
    public abstract Boolean isPermission();

    /**
     * getUserInfo
     *
     * @return Object
     */
    public abstract Object getUserInfo();

    /**
     * getWxUserInfo
     *
     * @return Object
     */
    public abstract Object getWxUserInfo();

    /**
     * isLogin
     *
     * @return Boolean
     */
    public abstract Boolean isLogin();

    /**
     * isWxLogin
     *
     * @return Boolean
     */
    public abstract Boolean isWxLogin();

    public void saveRsaInSession() {
        saveRsaInSession(PUBLIC_KEY);
    }

    public void saveRsaInSession(String attributeName) {
        RSAUtil.saveRsaInSession(this.request, attributeName);
    }

    public String decryptRSAParam(String base64Str) throws Exception {
        return RSAUtil.decryptWithPrivateKeyInSession(base64Str, this.request);
    }
}
